package utilities;

import java.io.Serializable;

/**
 * World date class.
 * @author pcdejager
 */
public final class WorldDate
    implements Serializable, Cloneable, Comparable<WorldDate> {
    /**
     * Default constructor.
     */
    public WorldDate() {
        ticks = 0;
    }
    /**
     * Construct date with ticks.
     * @param t The total ticks
     */
    public WorldDate(final int t) {
        ticks = t;
    }
    /**
     * Add days to the date.
     * @param days Number of days to add
     */
    public void addDays(final int days) {
        ticks += days;
    }
    /**
     * Add years to the date.
     * @param years Number of years to add
     */
    public void addYears(final int years) {
        ticks += (TimeProperties.getInstance().daysInAYear() * years);
    }
    /**
     * Return the year.
     * @return The year
     */
    public int year() {
        return TimeProperties.getInstance().getYear(ticks);
    }
    /**
     * Returns the month.
     * @return The month
     */
    public int month() {
        return TimeProperties.getInstance().getMonth(ticks);
    }
    /**
     * Returns the day.
     * @return The day
     */
    public int day() {
        return TimeProperties.getInstance().getDay(ticks);
    }
    /**
     * Get the total ticks since reference date.
     * @return The ticks
     */
    public int getTicks() {
        return ticks;
    }
    /**
     * Set the ticks since reference date.
     * @param t The ticks
     */
    public void setTicks(final int t) {
        ticks = t;
    }
    /**
     * Clone the date.
     * @return The cloned date
     */
    public Object clone() {
        return new WorldDate(ticks);
    }
    /**
     * Check if date after specified date.
     * @param when Date to check against
     * @return True if after, else false
     */
    public boolean after(final WorldDate when) {
        return ticks > when.getTicks();
    }
    /**
     * Check if date is before specified date.
     * @param when Date to check against
     * @return True if before, else false
     */
    public boolean before(final WorldDate when) {
        return ticks < when.getTicks();
    }
    /**
     * Check if dates are equal.
     * @param obj The object to check against
     * @return True if the same, else false
     */
    public boolean equals(final Object obj) {
        if (obj == null) {
            return false;
        }
        if (obj.getClass().equals(WorldDate.class)) {
            return (ticks == ((WorldDate) obj).getTicks());
        }
        return false;
    }
    /**
     * Compare two dates.
     * @param anotherDate Date to check against
     * @return Negative if before, 0 is equals, positive if after
     */
    public int compareTo(final WorldDate anotherDate) {
        return (ticks - anotherDate.getTicks());
    }
    /**
     * Get hash code.
     * @return The hash code
     */
    public int hashCode() {
        return (int) (ticks ^ (ticks >> 32));
    }
    /**
     * Create string of the date.
     * @return The date as a string
     */
    public String toString() {
        return String.valueOf(year())
                + "/"
                + String.valueOf(month())
                + "/"
                + String.valueOf(day());
    }

    /**
     * Calculate the number of years between two dates.
     * @param from The start date
     * @param to The end date
     * @return The number of years
     */
    public static int calculateYears(final WorldDate from, final WorldDate to) {
        return (to.getTicks() - from.getTicks())
                / TimeProperties.getInstance().daysInAYear();
    }
    /**
     * Calculate the number of days between two dates.
     * @param from The start date
     * @param to The end date
     * @return The number of days
     */
    public static int calculateDays(final WorldDate from, final WorldDate to) {
        return (to.getTicks() - from.getTicks());
    }

    /**
     * Total ticks since reference date.
     */
    private int ticks;
    /**
     * Serial version.
     */
    private static final long serialVersionUID = 1L;
}
